#include<iostream>
#include<sys/socket.h>
#include<arpa/inet.h>
#include<sys/types.h>        
#include<sys/socket.h>
#include<stdlib.h> //exit
#include<string.h> //memset
#include<stdio.h>//popen pclose
using namespace std;

//提高版本服务器：把从客户端获取到的内容当成指令去运行,然后把执行结果写回去给客户端
void Usage(std::string proc)
{
    cout << "Usage\n\t" <<proc <<" port"<<endl;
    exit(1);
}
int main(int argc,char* argv[])
{
    if(argc != 2)
    {
        Usage(argv[0]);
    }
    int sock = socket(AF_INET,SOCK_DGRAM,0);
    if(sock < 0)
    {
        perror("socket");
        exit(2);
    }
    cout <<"server:套接字创建成功..."<<endl;    
    struct sockaddr_in local;
    bzero(&local,sizeof(local));
    local.sin_family = AF_INET;
    local.sin_port = htons(atoi(argv[1]));
    local.sin_addr.s_addr = INADDR_ANY;
    if(bind(sock,(struct sockaddr*)&local,sizeof(local))<0)
    {
        perror("bind");
        exit(3);
    }
    cout <<"server:绑定成功...."<<endl;
    //提供服务
    cout <<"server:开始提供服务..."<<endl;
    bool quit = false;
    while(!quit)
    {
        struct sockaddr_in peer;//记录客户端的网络相关信息
        bzero(&peer,sizeof(peer));
        socklen_t len = sizeof(peer);
        char buf[1024] = {0};
        ssize_t cnt = recvfrom(sock,buf,sizeof(buf)-1,0,(struct sockaddr*)&peer,&len);
        if(cnt > 0)
        {
            buf[cnt] = 0;
            cout <<"client# " << buf << endl;
            FILE* pf = popen(buf,"r");
            if(NULL == pf)
            {
                perror("popen");
                continue;
            }
            char msg[1024] = {0};
            string reply ;
            while(fgets(msg,sizeof(msg),pf) != NULL)
                reply += msg;
            pclose(pf);//注意需要关闭文件流,防止泄露
            //发送响应
            sendto(sock,reply.c_str(),reply.size(),0,(struct sockaddr*)&peer,len);
        }
        else
        {
            perror("recvfrom");
            continue;
        }
    }
    return 0;
}
